#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>

#include <iostream>

#include <json/json.h>
#include <log4cxx/logger.h>

#include "DataSvrHelper.h"

using std::cout;
using std::endl;

using namespace log4cxx;

static LoggerPtr g_logger = Logger::getLogger("DataSvrHelper");


int parse_control_file(const char * control_file_path, vector<uint32_t> & crcs) {
        if (NULL == control_file_path) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", invalid args");
                return -1;
        }
	struct stat s;
	int ret = stat(control_file_path, &s);
	if (0 != ret) {
		LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", stat error, file:" << control_file_path << ", ret:" << ret << \
				", errno:" << errno);
		return -2;
	}
	char * buf = new char[s.st_size + 1];
	bzero(buf, s.st_size + 1);
	FILE * fp = fopen(control_file_path, "r");
	if (NULL == fp) {
		delete[] buf;
		LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", fopen error, file:" << control_file_path << ", errno:" << errno);
		return -3;
	}
	int n = fread(buf, s.st_size, 1, fp);
	fclose(fp);
	if (1 != n) {
		delete[] buf;
		LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", fread error, file:" << control_file_path << ", errno:" << errno);
		return -4;
	}
        json_object * j = json_tokener_parse(buf);
        if (is_error(j)) {
		delete[] buf;
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", parse json string, file:" << control_file_path << ", content:" << buf);
                return -5;
        }
        json_object * j_crc = json_object_object_get(j, "CRC");
     	if (is_error(j_crc)) {
		delete[] buf;
		json_object_put(j);
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", get crc error:" << buf);
                return -6;
        }
	for(int i=0; i < json_object_array_length(j_crc); i++) {
		json_object * j_t = json_object_array_get_idx(j_crc, i);
		crcs.push_back(json_object_get_int(j_t));
	}
	delete[] buf;
	json_object_put(j);
	return 1;
}

int write_control_file(const char * control_file_path, const vector<uint32_t> crcs) {
	if (NULL == control_file_path) {
		LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", invalid args");
		return -1;
	}
	json_object * j = json_object_new_object();
	json_object * j_crc = json_object_new_array();
	for (vector<uint32_t>::const_iterator iter = crcs.begin(); crcs.end() != iter; iter++) {
		json_object * j_t = json_object_new_int(*iter);
		json_object_array_add(j_crc, j_t);
	}
	json_object_object_add(j, "CRC", j_crc);
	string content = json_object_to_json_string(j);
	json_object_put(j);
	FILE * fp = fopen(control_file_path, "w");
	if (NULL == fp) {
		LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", fopen error, file:" << control_file_path << ", errno:" << errno);
		return -2;
	}
	int n = fwrite(content.c_str(), content.size(), 1, fp);
	fclose(fp);
	if (1 != n) {
		LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", fwrite error, file:" << control_file_path << ", errno:" << errno << \
				", content:" << content);
		return -3;
	}
	return 1;
}

int write_crc_to_control_file(const char * control_file_path, const vector<uint32_t> new_crcs) { 
	if (NULL == control_file_path) {
		LOG4CXX_ERROR(g_logger, __FUNCTION__ << "invalid args");
		return -1;
	}
	vector<uint32_t> old_crcs;
	int ret = parse_control_file(control_file_path, old_crcs);
	if (ret < 0) {
		LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", parse control file error, file:" << control_file_path << ", ret:" << \
				ret);
		return -2;
	}
	
	ret = write_control_file(control_file_path, new_crcs);
	if (ret < 0) {
		LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", write control file error, file:" << control_file_path << \
				", ret:" << ret);
		return -3;
	}
	return 1;
}
